#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dlist.h"

node_t *create_dlist()
{
	// 动态分配内存
	node_t *head = (node_t *)malloc(sizeof(node_t)); 
	// 参数检查
	if(!head)
		return NULL;

	// 链表初始化
	head->data = NULL;
	head->pre = head;
	head->next = head;

	return head;
}

int is_empty_dlist(node_t *head)
{
	// 参数检查
	if(!head)
		return -1;

	if(head->next == head)
		return 1; // 1为真，即链表为空
	else
		return 0; // 0为假，即链表不为空
}

int insert_hdlist(node_t *head, void *data, int len)
{
	// 参数检查
	if((!head) || (!data) || (len <= 0))
		return -1;

	// 申请节点内存
	node_t *new_node = (node_t *)malloc(sizeof(node_t));
	// 检查是否申请成功
	if(!new_node)
		return -1;
	// memset可以将一段内存的前n个字节设置为特定的值，通常为新申请的内存进行初始化
	memset(new_node, 0, sizeof(node_t));

	// 申请节点数据内存
	new_node->data = malloc(len);
	if(!new_node->data)
	{
		free(new_node);
		return -1;
	}
	memset(new_node->data, 0, len);

	// 拷贝数据
	memcpy(new_node->data, data, len);

	// 从头部挂载
	new_node->pre = head; 
	new_node->next = head->next;
	head->next->pre = new_node; 
	head->next = new_node;

	return 0;
}

int insert_tdlist(node_t *head, void *data, int len)
{
	// 检查参数
	if((!head) || (!data) || (len <= 0))
		return -1;

	// 申请节点内存
	node_t *new_node = (node_t *)malloc(sizeof(node_t));
	// 检查申请是否成功
	if(!new_node)
		return -1;
	// 节点初始化
	memset(new_node, 0, sizeof(node_t));

	// 申请节点数据内存
	new_node->data = malloc(len);
	// 检查申请是否成功
	if(!new_node->data)
	{
		free(new_node);
		return -1;
	}
	// 节点数据初始化
	memset(new_node->data, 0, len);

	// 拷贝数据
	memcpy(new_node->data, data, len);

	// 从尾部挂载
	new_node->pre = head->pre;
	new_node->next = head;
	head->pre->next = new_node;
	head->pre =new_node;

	return 0;
}

void show_dlist(node_t *head, pfunc_show_t show_func)
{
	// 检查参数
	if(!head)
		return ;

	// 判断head是否为空
	if(is_empty_dlist(head))
		return ;

	// 循环遍历
	node_t *temp = head->next;
	while(temp != head)
	{
		// 调用打印函数
		show_func(temp->data);
		temp = temp->next;
	}

	return ;
}

int delete_hdlist(node_t *head)
{
	// 检查参数
	if(!head)
		return -1;

	// 判断链表是否为空
	if(is_empty_dlist(head))
		return -1;

	// 摘链
	node_t *temp = head->next;
	head->next = temp->next;
	head->next->pre = head;

	// 释放内存
	free(temp->data);
	free(temp);

	return 0;
}

int delete_tdlist(node_t *head)
{
	if(!head)
		return -1;

	if(is_empty_dlist(head))
		return -1;

	node_t *temp = head->pre;
	head->pre = temp->pre;
	head->pre->next = head;

	free(temp->data);
	free(temp);

	return 0;
}

int destroy_dlist(node_t **head)
{
	// 检查参数
	if((!head) || (!(*head)))
		return -1;

	// 循环遍历
	node_t *temp = (*head)->next;
	while(temp != (*head))
	{
		// 摘链
		(*head)->next = temp->next;
		(*head)->next->pre = (*head);

		// 释放内存
		free(temp->data);
		free(temp);

		// 取下一个节点
		temp = temp->next;
	}

	// 释放链表头
	free(*head);
	*head = NULL;

	return 0;
}

int modify_dlist(node_t *head, void *old_data, void *new_data, int len)
{
	// 参数检查
	if((!head) || (!old_data) || (!new_data) || (len <= 0))
		return -1;

	// 判断链表是否为空
	if(is_empty_dlist(head))
		return -1;

	// 循环查找节点比较数据
	node_t *temp = head->next;
	while(temp != head)
	{
		if(memcmp(temp->data, old_data, len) == 0) // 比较两个内存区域的数据是否相等
		{
			// 拷贝数据
			memcpy(temp->data, new_data, len);
			break;
		}
		// 获取下一个节点
		temp = temp->next;
	}

	// 如果节点地址和head相同，则没有找到相应的数据
	if(temp == head)
		return -1;

	return 0;
}

node_t *find_dlist(node_t *head, void *data, pfunc_cmp_t cmp_func)
{
	// 参数检查
	if((!head) || (!data))
		return NULL;

	// 判断链表是否为空
	if(is_empty_dlist(head))
		return NULL;

	// 循环遍历需要比较的数据
	node_t *temp = head->next;
	while(temp != head)
	{
		if(cmp_func(temp->data, data) == 0)
		{
			break;
		}
		temp = temp->next;
	}

	// 如果节点地址和head相同，在没有找到相应的数据
	if(temp == head)
		return NULL;

	return temp;
}
